
import * as vscode from 'vscode';
import { ginfo } from './extension';
import * as fs from "fs";
import * as P from "path";
import { GetFilesSync } from './fstool';
import { TTPathTool } from './pathtool';
import { FormatMgr } from './formatmgr';

var mapWebPanels: { [id: string]: vscode.WebviewPanel } = {};

export function OpenPreview(uri: vscode.Uri, p1: any) {

    let ext = TTPathTool.GetExt(uri.fsPath);
    let info = FormatMgr.Instance().GetFormatInfo(uri.fsPath);
    if (info == null) {
        vscode.window.showInformationMessage("不支持的文件格式");
        return;
    }


    //其实我们只关心一个情况，就是文件从外部修改了，这时候我们需要通知webview刷新
    vscode.workspace.onDidChangeTextDocument(async (e) => {
        let view = mapWebPanels[e.document.uri.toString()];
        if (view == undefined)
            return;
        console.log("外部修改中...");
        //src_fix 只有vscode 才能知道，不好模拟，不用太关注他
        await view.webview.postMessage({ cmd: "src_fix" });
    });
    vscode.workspace.onDidSaveTextDocument(async (e) => {
        let view = mapWebPanels[e.uri.toString()];
        if (view == undefined)
            return;
        console.log("外部已修改...");
        //src_fixed 是需要重点关注的事件，这说明文件已从外部被修改，webview 根据情况，需要做出反应
        await view.webview.postMessage({ cmd: "src_fixed" });
    });
    // vscode.workspace.onDidCloseTextDocument(async (e) => {
    //     let view = mapWebPanels[e.uri.toString()];
    //     if (view == undefined)
    //         return;
    //     let _uri = view.webview.asWebviewUri(e.uri);
    //     await view.webview.postMessage({ command: "close", "uri": _uri.toString() });
    // });
    // vscode.workspace.onDidOpenTextDocument(async (e) => {
    //     let view = mapWebPanels[e.uri.toString()];
    //     if (view == undefined)
    //         return;
    //     let _uri = view.webview.asWebviewUri(e.uri);
    //     await view.webview.postMessage({ command: "open", "uri": _uri.toString() });
    // });

    //当多个文件公用一个预览才能这么干
    // vscode.window.onDidChangeActiveTextEditor(async (e) => {
    //     let _uri = e.document.uri;
    //     let view = mapWebPanels[_uri.toString()];
    //     view.reveal();
    // });
    let edit_folder = TTPathTool.GetPathName(uri.fsPath);
    let editfilename = TTPathTool.GetFileName(uri.fsPath);

    console.log("打开TTEditor :" + editfilename);

    let panel = mapWebPanels[uri.toString()];
    if (panel != null) {
        panel.reveal();
        return;
    }

    let htmlpath = vscode.Uri.joinPath(ginfo.baseexturi, "htmlview");
    //let srcpath = vscode.Uri.joinPath(ginfo.baseexturi, "out/webview_p1");
    let option: vscode.WebviewOptions | vscode.WebviewPanelOptions = {
        enableScripts: true,//是否允许webview中执行js，那必须的啊
        retainContextWhenHidden: true
        //localResourceRoots: [ginfo.baseexturi,htmlpath,srcpath]//如果要允许访问本地文件，这里需要配置路径
    };

    panel = vscode.window.createWebviewPanel("ttwin", "hello tt", vscode.ViewColumn.Active, option);
    // let _htmlurl = vscode.Uri.joinPath(ginfo.baseexturi, "webview_p1/index.html");
    // _htmlurl = panel.webview.asWebviewUri(_htmlurl)

    // let _htmlsrcurl = vscode.Uri.joinPath(ginfo.baseexturi, "out/webview_p1/main.js");
    // _htmlsrcurl = panel.webview.asWebviewUri(_htmlsrcurl)
    // let _htmlurl2 = vscode.Uri.joinPath(ginfo.baseexturi, "webview_p1/t1.png");
    // _htmlurl2 = panel.webview.asWebviewUri(_htmlurl2)

    //这里不能使用完整的main.js，只能使用pack.js 因为 vscode 内嵌webview 不支持 es6 module
    panel.webview.html = GetMainHtml(panel.webview, htmlpath, info.initscript, editfilename);
    panel.title = "TT<" + editfilename + ">"

    panel.webview.onDidReceiveMessage(async (json) => {
        let cmd = "";
        try {
            //收到webview中的数据咋整
            cmd = json["cmd"];
            if (cmd != undefined) {
                //console.log("recv:" + cmd);
                if (cmd == "fs_find") {

                    let path = json["data"]["path"] as string;
                    let depth = json["data"]["depth"] as number;
                    if (depth == undefined)
                        depth = 3;
                    let files = GetFilesSync(edit_folder, path, depth);

                    let outjson = { cmd: "filelist", data: files, "path": path }
                    await panel.webview.postMessage(outjson);
                    return;
                }
                else if (cmd == "fs_load_text") {
                    let path = json["data"] as string;
                    let fullpath = "";
                    if(P.isAbsolute(path))
                    {
                        fullpath =path;
                    }
                    else
                    {
                        fullpath = P.join(edit_folder, path);
                    }

                    let txt = fs.readFileSync(fullpath, { encoding: "utf-8" });
                    let outjson = { cmd: "filedata", data: txt, "filename": path, "format": "text" }
                    await panel.webview.postMessage(outjson);
                    return;
                }
                else if (cmd == "fs_load_binary") {

                    let path = json["data"] as string;
                    let fullpath = "";
                    if(P.isAbsolute(path))
                    {
                        fullpath =path;
                    }
                    else
                    {
                        fullpath = P.join(edit_folder, path);
                    }
                    let bin = fs.readFileSync(fullpath);
                    let outjson = { cmd: "filedata", data: bin.toString("hex"), "filename": path, "format": "binary" }
                    await panel.webview.postMessage(outjson);
                    return;
                }
                else if (cmd == "fs_save_text") {
                    let data = json["data"]["data"] as string;
                    let filename = json["data"]["filename"] as string;
                    let fullpath = "";
                    if(P.isAbsolute(filename))
                    {
                        fullpath =filename;
                    }
                    else
                    {
                        fullpath = P.join(edit_folder, filename);
                    }
                    //fs.unlinkSync(filename);
                    fs.writeFileSync(fullpath, data);
                    return;
                }
                else if (cmd == "fs_save_binary") {
                    let hexstr = json["data"]["data"] as string;
                    let filename = json["data"]["filename"] as string;
                    let data = Buffer.from(hexstr, "hex");
                    let fullpath = "";
                    if(P.isAbsolute(filename))
                    {
                        fullpath =filename;
                    }
                    else
                    {
                        fullpath = P.join(edit_folder, filename);
                    }
                    //filename = P.join(edit_folder, filename);
                    //fs.unlinkSync(filename);
                    fs.writeFileSync(fullpath, data);
                    return;
                }
                else {
                    console.warn("recv unknown cmd:" + cmd);
                }
            }
            else {
                console.warn("recv unknown." + JSON.stringify(json));
            }
        }
        catch (e) {
            let outjson = { cmd: "onerror", data: "error", srccmd: cmd, "error": e }
            let send = JSON.stringify(outjson);
            await panel.webview.postMessage(outjson);
            console.log("ws error:" + send);
        }

    });
    panel.onDidDispose(() => {
        delete mapWebPanels[uri.toString()]
        panel = null;
    });

    mapWebPanels[uri.toString()] = panel;
}

function GetMainHtml(webview: vscode.Webview, htmlpath: vscode.Uri, initscript: string, editfilename: string): string {
    let url = webview.asWebviewUri(htmlpath).toString();
    //console.log("_htmlurl = " + url);

    let initjs = GetInitJS(url, editfilename);
    let mainjs = url + "/" + initscript;
    return `<html>
    <head>
    <script>
    `
        + initjs +
        `</script>
    <script type="module" src="`+ mainjs + `"></script>
    </head>
    <body>
    </body>
    </html>
    `;
}

function GetInitJS(htmlurl: string, editfilename: string): string {
    let header = `"use strict";
let plugin_path = "`+ htmlurl + `";
let edit_filename = "`+ editfilename + `";
`
    let js = `
//下面是固定代码
function getVsCodeEditFileName() {
return edit_filename;
}
function getVsCodePluginPath() {
return plugin_path;
}
`
    return header + js;
}


